// +FHDR------------------------------------------------------------
//                 Copyright (c) 2023 NOVAUTO.
//                       ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename      : async_fifo.v
// Author        : ICer
// Created On    : 2023-12-28 18:15
// Last Modified : 2024-01-10 15:40 by ICer
// -----------------------------------------------------------------
// Description:
//
//
// -FHDR------------------------------------------------------------


module async_fifo #(
    //parameter
    parameter WIDTH = 8,
    parameter DEPTH = 10
)( /*AUTOARG*/
   // Outputs
   wfull, rdata, rempty,
   // Inputs
   w_clk, w_rst_n, r_clk, r_rst_n, winc, wdata, rinc
   );

// ----------------------------------------------------------------
// Interface declare
// ----------------------------------------------------------------
input             w_clk;
input             w_rst_n;

input             r_clk;
input             r_rst_n;

input             winc;
input [WIDTH -1:0]wdata;
output            wfull;

input             rinc;
output[WIDTH -1:0]rdata;
output            rempty;

// ----------------------------------------------------------------
// Wire declare
// ----------------------------------------------------------------
localparam ADDR_WD    = $clog2(DEPTH);
localparam ADDR_WD_WX = ADDR_WD + 1;

// ----------------------------------------------------------------
// AUTO declare
// ----------------------------------------------------------------
/*AUTOOUTPUT*/
/*AUTOINPUT*/
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire [$clog2(DEPTH):0]  raddr;                  // From u_r_ctrl of async_fifo_r_ctrl.v
wire [ADDR_WD_WX-1:0]   raddr_sync;             // From u_r2w_sync of async_fifo_sync_path.v
wire [$clog2(DEPTH):0]  raddr_to_write;         // From u_r_ctrl of async_fifo_r_ctrl.v
wire                    renc;                   // From u_r_ctrl of async_fifo_r_ctrl.v
wire [$clog2(DEPTH):0]  waddr;                  // From u_w_ctrl of async_fifo_w_ctrl.v
wire [ADDR_WD_WX-1:0]   waddr_sync;             // From u_w2r_sync of async_fifo_sync_path.v
wire [$clog2(DEPTH):0]  waddr_to_read;          // From u_w_ctrl of async_fifo_w_ctrl.v
wire                    wenc;                   // From u_w_ctrl of async_fifo_w_ctrl.v
// End of automatics

/*async_fifo_w_ctrl AUTO_TEMPLATE(
.clk(w_clk),
.rst_n(w_rst_n),
);
*/
async_fifo_w_ctrl #(/*AUTOINSTPARAM*/
                    // Parameters
                    .DEPTH              (DEPTH)) 
u_w_ctrl(/*AUTOINST*/
         // Outputs
         .wenc                          (wenc),
         .waddr                         (waddr[$clog2(DEPTH):0]),
         .waddr_to_read                 (waddr_to_read[$clog2(DEPTH):0]),
         .wfull                         (wfull),
         // Inputs
         .clk                           (w_clk),                 // Templated
         .rst_n                         (w_rst_n),               // Templated
         .winc                          (winc),
         .raddr_sync                    (raddr_sync[$clog2(DEPTH):0]));

/*async_fifo_sync_path AUTO_TEMPLATE(
.SYNC_CYC(3),
.WIDTH(ADDR_WD_WX),

.in_clk(w_clk),
.in_rst_n(w_rst_n),
.out_clk(r_clk),
.out_rst_n(r_rst_n),
.in_data(waddr_to_read[]),
.out_data(waddr_sync[]),
);
*/
async_fifo_sync_path #(/*AUTOINSTPARAM*/
                       // Parameters
                       .SYNC_CYC        (3),                     // Templated
                       .WIDTH           (ADDR_WD_WX))            // Templated
u_w2r_sync(/*AUTOINST*/
           // Outputs
           .out_data                    (waddr_sync[ADDR_WD_WX-1:0]), // Templated
           // Inputs
           .in_clk                      (w_clk),                 // Templated
           .in_rst_n                    (w_rst_n),               // Templated
           .out_clk                     (r_clk),                 // Templated
           .out_rst_n                   (r_rst_n),               // Templated
           .in_data                     (waddr_to_read[ADDR_WD_WX-1:0])); // Templated

/*async_fifo_r_ctrl AUTO_TEMPLATE(
.clk(r_clk),
.rst_n(r_rst_n),
);
*/
async_fifo_r_ctrl #(/*AUTOINSTPARAM*/
                    // Parameters
                    .DEPTH              (DEPTH)) 
u_r_ctrl(/*AUTOINST*/
         // Outputs
         .renc                          (renc),
         .raddr                         (raddr[$clog2(DEPTH):0]),
         .raddr_to_write                (raddr_to_write[$clog2(DEPTH):0]),
         .rempty                        (rempty),
         // Inputs
         .clk                           (r_clk),                 // Templated
         .rst_n                         (r_rst_n),               // Templated
         .rinc                          (rinc),
         .waddr_sync                    (waddr_sync[$clog2(DEPTH):0]));

/*async_fifo_sync_path AUTO_TEMPLATE(
.SYNC_CYC(3),
.WIDTH(ADDR_WD_WX),

.in_clk(r_clk),
.in_rst_n(r_rst_n),
.out_clk(w_clk),
.out_rst_n(w_rst_n),
.in_data(raddr_to_write[]),
.out_data(raddr_sync[]),
);
*/
async_fifo_sync_path #(/*AUTOINSTPARAM*/
                       // Parameters
                       .SYNC_CYC        (3),                     // Templated
                       .WIDTH           (ADDR_WD_WX))            // Templated
u_r2w_sync(/*AUTOINST*/
           // Outputs
           .out_data                    (raddr_sync[ADDR_WD_WX-1:0]), // Templated
           // Inputs
           .in_clk                      (r_clk),                 // Templated
           .in_rst_n                    (r_rst_n),               // Templated
           .out_clk                     (w_clk),                 // Templated
           .out_rst_n                   (w_rst_n),               // Templated
           .in_data                     (raddr_to_write[ADDR_WD_WX-1:0])); // Templated

/*dual_port_reg AUTO_TEMPLATE(
.wclk(w_clk),
.rclk(r_clk),
);
*/
dual_port_reg #(/*AUTOINSTPARAM*/
                // Parameters
                .DEPTH                  (DEPTH),
                .WIDTH                  (WIDTH))
u_ram(/*AUTOINST*/
      // Outputs
      .rdata                            (rdata[WIDTH-1:0]),
      // Inputs
      .wclk                             (w_clk),                 // Templated
      .wenc                             (wenc),
      .waddr                            (waddr[$clog2(DEPTH)-1:0]),
      .wdata                            (wdata[WIDTH-1:0]),
      .rclk                             (r_clk),                 // Templated
      .renc                             (renc),
      .raddr                            (raddr[$clog2(DEPTH)-1:0]));

endmodule
// Local Variables:
// verilog-auto-inst-param-value:t
// verilog-library-directories:(".")
// verilog-library-extensions:(".v")
// End:

